package tripx.blog;

import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

import com.google.gson.Gson;
import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonParser;

/**
 * Wrapper for <code></b>BlogService</b></code>, BlogService provides the
 * standard interfaces.
 * 
 * @author zhb
 * 
 */
public class BlogServiceWrapper {

	// target service
	private BlogService service;

	public BlogServiceWrapper() {
		service = new BlogService();
	}

	/**
	 * get the <code><b>Blog</code></b> specified by the uname, cname and time,
	 * 
	 * @param uname
	 *            userName
	 * @param cname
	 *            cityName
	 * @param time
	 *            trip time
	 * @return
	 */
	public String getBlog(String uname, String cname, String time) {
		int uid = service.queryInteger("getUserIdByName", uname);
		int cid = service.queryInteger("getCityIdByName", cname);
		if (uid == -1 || cid == -1) {
			return new Gson().toJson(null);
		}
		String result = service.query("getBlog", uid + "", cid + "", time);
		// if the result is null or is empty, return null
		if (result.equals("[]")) {
			return new Gson().toJson(null);
		} else {
			Gson gson = new Gson();
			JsonParser parser = new JsonParser();
			JsonArray array = parser.parse(result).getAsJsonArray();

			ArrayList<DbBlog> blogList = new ArrayList<DbBlog>();
			for (JsonElement ele : array) {
				blogList.add(gson.fromJson(ele, DbBlog.class));
			}
			// we can assert there is only one result.
			DbBlog blog = blogList.get(0);

			// get images
			File imageDir = new File(service.getImageBaseDirPath() + "/"
					+ uname + "/" + cname + "/" + time);
			String[] fileNames = imageDir.list();
			ArrayList<String> imageNames = new ArrayList<String>();
			for (String fileName : fileNames) {
				imageNames.add(fileName);
			}
			return gson.toJson(new Blog(blog.uid + "", blog.time,
					blog.cid + "", blog.html, imageNames));
		}
	}

	/**
	 * add a new <code><b>Blog</b></code>
	 * 
	 * @param blog
	 * @return
	 */
	public boolean addBlog(String json) {
		Gson gson = new Gson();
		Blog blog = gson.fromJson(json, Blog.class);
		String cname = blog.getCity();
		String uname = blog.getUsername();
		int cid = service.queryInteger("getCityIdByName", cname);
		int uid = service.queryInteger("getUserIdByName", uname);
		if (cid == -1 || uid == -1) {
			return false;
		}
		DbBlog dBlog = new DbBlog(blog.getContent(), cid, uid, blog.getTime());
		return service.addBlog(dBlog);
	}

	/**
	 * delete the specified Blog
	 * 
	 * @param uname
	 *            user name
	 * @param cid
	 *            city name
	 * @param time
	 * @return
	 */
	public boolean deleteBlog(String uname, String cname, String time) {
		int cid = service.queryInteger("getCityIdByName", cname);
		int uid = service.queryInteger("getUserIdByName", uname);
		if (cid == -1 || uid == -1) {
			return false;
		}
		HashMap<String, String> kvMap = new HashMap<String, String>();
		kvMap.put("uid", uid + "");
		kvMap.put("cid", cid + "");
		kvMap.put("time", time);
		return service.deleteBlog(kvMap);
	}

	/**
	 * update the blog which specified by the uname, cname, and time, and
	 * replace the content with the new html
	 * 
	 * @param uname
	 *            user name
	 * @param cname
	 *            city name
	 * @param time
	 * @param html
	 * @return
	 */
	public boolean updateBlog(String uname, String cname, String time,
			String html) {
		int cid = service.queryInteger("getCityIdByName", cname);
		int uid = service.queryInteger("getUserIdByName", uname);
		if (cid == -1 || uid == -1) {
			return false;
		}
		HashMap<String, String> conditionMap = new HashMap<String, String>();
		conditionMap.put("uid", uid + "");
		conditionMap.put("cid", cid + "");
		conditionMap.put("time", time);
		return service.modifyBlog("html", html, conditionMap);
	}

	/**
	 * get the <code><b>TimeLine</b></code> information.
	 * <p>
	 * The TimeLine includes the number of blog and the time on each blog.
	 * </p>
	 * 
	 * @param uid
	 *            user id
	 * @param cid
	 *            city id
	 * @return
	 */
	public String getTimeLine(String uname, String cname) {
		int cid = service.queryInteger("getCityIdByName", cname);
		int uid = service.queryInteger("getUserIdByName", uname);
		if (cid == -1 || uid == -1) {
			return new Gson().toJson(null);
		}
		String result = service.query("getTimeList", uid + "", cid + "");
		if (result == null) {
			return new Gson().toJson(null);
		} else {
			Gson gson = new Gson();
			JsonParser parser = new JsonParser();
			JsonArray array = parser.parse(result).getAsJsonArray();

			ArrayList<DbTime> timeList = new ArrayList<DbTime>();
			for (JsonElement ele : array) {
				timeList.add(gson.fromJson(ele, DbTime.class));
			}
			// translate it to the TimeLine object
			int size = timeList.size();
			ArrayList<String> times = new ArrayList<String>();
			for (DbTime time : timeList) {
				times.add(time.time);
			}
			return gson.toJson(new TimeLine(size, times));
		}
	}

	/**
	 * upload a new Image
	 * 
	 * @param imageName
	 * @param imageData
	 * @return
	 */
	public boolean uploadImage(String fullPath, byte[] imageData) {
		String formatName = fullPath.substring(fullPath.lastIndexOf('.') + 1)
				.toUpperCase();
		return service.uploadImage(imageData, fullPath, formatName);
	}

	/**
	 * download the specified Image
	 * 
	 * @param fullName
	 *            consist of the <strong>uid/cid/*.png</strong>
	 * @return a Byte Array contains the Image data
	 */
	public byte[] downloadImage(String fullPath) {
		String formatName = fullPath.substring(fullPath.lastIndexOf('.') + 1)
				.toUpperCase();
		return service.downloadImage(fullPath, formatName);
	}

	/**
	 * delete all the images of the blog, always be true
	 * 
	 * @param fullPaths
	 * @return
	 */
	public boolean deleteImages(List<String> fullPaths) {
		for (String imageName : fullPaths) {
			service.deleteImage(imageName);
		}
		return true;
	}
}
